package com.linkoog.devtools.type.jackson;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import com.linkoog.devtools.type.LiteralType;
import com.linkoog.devtools.type.Type;
import com.linkoog.devtools.type.impl.LiteralTypes;
import com.linkoog.devtools.utils.ClassFieldsUtils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.List;

public class TypeJsonSerializer extends StdSerializer<Type> {

    public TypeJsonSerializer() {
        super(Type.class);
    }

    @Override
    public void serialize(Type value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        if (value == null){
            gen.writeNull();
            return;
        }

        gen.writeStartObject();
        if (!( value instanceof LiteralType)){
            gen.writeStringField("@type", value.getClass().getName());
            gen.writeStringField("typeName", value.getTypeName());
            gen.writeStringField("typeFullName", value.getTypeFullName());
        } else {
            if (value instanceof LiteralTypes){
                LiteralTypes literalTypes = (LiteralTypes) value;
                gen.writeStringField("@type", "LiteralTypeEnum#" + literalTypes.name());
            }else {
                gen.writeStringField("@type", value.getClass().getName());
            }
        }

        final List<Field> fields = ClassFieldsUtils.getAllFields(value.getClass());
        for (Field field : fields) {
            boolean isTransient = Modifier.isTransient(field.getModifiers());
            boolean isStatic = Modifier.isStatic(field.getModifiers());
            if (isTransient || isStatic){
                continue;
            }

            if ("typeName".equals(field.getName()) || "typeFullName".equals(field.getName()) ){
                continue;
            }

            try {
                field.setAccessible(true);
                gen.writeObjectField(field.getName(), field.get(value));
            } catch (IllegalAccessException ignored) {
            }
        }
        gen.writeEndObject();
    }

}
